#!/usr/bin/env python
# -*- coding: utf-8 -*-
import sys, os
parpath=os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
sys.path.append(parpath)

from cmds import *
from server import *
from client import *

class Game(object):
    '''游戏类，处理游戏配置和逻辑'''

    def __init__(self):
        #游戏服务器
        self.server=None
        #游戏模块名称
        self.moduleName='general'
        #游戏名称
        self.name='game'
        #被标记的玩家id，一般代表占出牌主动权的玩家（或每一轮首先出牌的玩家）
        self.markPlayerId=0
        #令牌玩家id，一般代表当前该动作的玩家
        self.tokenPlayerId=0
        #该游戏的牌大小顺序
        self.cardOrder=range(54)
        #基数牌（最小牌）
        self.baseCard=Card(DIAMOND, THREE)
        #牌局计数
        self.round=0
    
    def configure(self):
        #引入各类资源，方便使用
        self.table=self.server.table
        self.players=self.server.players
        self.playerCount=self.server.playerCount
        self.cardBox=self.table.cardBox
        self.scoreBox=self.table.scoreBox
        self.inList=self.table.inList
        self.outList=self.table.outList
        self.cardPack=self.table.cardPack
        self.cardBase=self.table.cardBase

    def notifyAll(self, *args):
        '''对server.notifyAll的封装，方便使用'''
        args=list(args)
        op=args[0]
        #如果第一参数不是操作者id，则当成传入操作者对象，转换为id
        if type(op)!=int:
            args[0]=op.info['id']
        self.server.notifyAll(args)

    def notifyInitGameData(self, specdata={}):
        '''通知更新初始游戏数据'''
        gamedata={
            'mGameName':self.moduleName, 
            'name':self.name, 
            'playerCount':self.playerCount, 
            'playerInfo':[player.info for player in self.players], 
            'cardboxCount':len(self.cardBox), 
            'playerCardCount':[len(player.cardList) for player in self.players], 
            'scoreBox':self.scoreBox[:], 
            'inList':self.inList[:], 
            'outList':self.outList[:], 
            'markPlayerId':self.markPlayerId,
            'tokenPlayerId':self.tokenPlayerId, 
            'cardOrder':self.cardOrder, 
            'cardPack':self.cardPack, 
            'cardBase':self.cardBase, 
            'round':self.round, 
        }
        #追加特定数据
        for k, v in specdata.iteritems():
            gamedata[k]=v
        self.notifyAll(SERVERID, SETGAMEDATA, gamedata)

    def notifyGameData(self, specdata={}):
        '''通知更新游戏数据(运行中变化)'''
        gamedata={
            'cardboxCount':len(self.cardBox), 
            'playerCardCount':[len(player.cardList) for player in self.players], 
            'scoreBox':self.scoreBox[:], 
            'inList':self.inList[:], 
            'outList':self.outList[:], 
            'markPlayerId':self.markPlayerId, 
            'tokenPlayerId':self.tokenPlayerId, 
        }
        #追加特定数据
        for k, v in specdata.iteritems():
            gamedata[k]=v
        self.notifyAll(SERVERID, UPDATEGAMEDATA, gamedata)
    
    def setMarkPlayerId(self, player):
        '''设置标记玩家id'''
        self.markPlayerId=player.info['id']
        
    def clearOutList(self):
        '''清空牌桌出牌序列'''
        self.outList[:]=[[] for i in range(self.playerCount)]
        self.notifyAll(SERVERID, CLEAROUTLIST)
    
    def clearInList(self):
        '''清空牌桌收牌列表'''
        self.inList[:]=[[] for i in range(self.playerCount)]
    
    def begin(self):
        '''开始游戏，较为通用的程序'''
        self.configure()
        while self.server.getState()==GameServer.RUNNING:
            self.round+=1
            for player in self.players:
                player.do(RESETDATA)
            self.table.fillCardBox()
            self.table.shuffle()
            self.clearOutList()
            self.clearInList()
            self.notifyInitGameData()
            try:
                #开始一局游戏流程
                self.beginRound()
            except Exception, e:
                import sys, traceback
                traceback.print_exc()
                return
            self.server.setState(GameServer.WAITING)
            self.server.waitReady()
    
    def beginRound(self):
        '''一局游戏流程'''
        self.deal()
        self.play()
    
    def calcScore(self, *args):
        '''计算玩家积分，待定'''
        pass
    
    def judge(self, *args):
        '''出牌有效判定，待定'''
        return OK
    
    def deal(self):
        '''发牌，较为通用的程序'''
        self.notifyAll(SERVERID, SHOWMESSAGE, u'***发牌***')
        i=self.markPlayerId
        while self.cardBox:
            self.tokenPlayerId=i
            self.notifyGameData()
            player=self.players[i]
            card=self.cardBox.pop()
            cards=[card]
            cmd_data=player.do(TAKECARD, cards)
            if not cmd_data:
                #连接错误，终止游戏
                raise Exception('game error')
            #通知各玩家
            self.notifyAll(player, TAKECARD)
            #按座位顺序轮流摸牌
            i+=1
            i%=self.playerCount

    def play(self):
        '''打牌，较为通用的程序'''
        self.notifyAll(SERVERID, SHOWMESSAGE, u'***打牌***')
        #首次出牌id
        i=self.markPlayerId
        while True:
            self.tokenPlayerId=i
            if i==self.markPlayerId:
                #表示一轮牌开始
                self.clearOutList()
            self.notifyGameData()
            player=self.players[i]
            cmd_data=player.do(PLAYCARD)
            if not cmd_data:
                raise Exception('game error')
            cmd, cards=cmd_data
            r=self.judge(player, cards)
            if r==UNDO:
                #出牌无效，撤回
                player.do(UNDO, PLAYCARD)
            elif r==OK:
                #出牌有效
                #填牌桌出牌列表
                self.outList[i]=cards
                #通知各玩家动作和更新游戏数据
                self.notifyAll(player, PLAYCARD, cards)
                #该玩家没牌即赢，结束
                if not player.cardList:
                    #算分
                    self.calcScore()
                    self.notifyGameData()
                    self.notifyAll(player, WIN)
                    break
                i+=1
                i%=self.playerCount


class AI(object):
    '''人工智能类，机器人的头脑，根据相应游戏逻辑做出决策'''
    def __init__(self):
        self.player=None
    
    def initData(self):
        pass
    
    def playCard(self):
        pass
    
    def showCard(self):
        pass
    
    def giveCard(self):
        pass

if __name__ == '__main__':
    pass
